package com.idealighter.game.server.net.http;

import com.google.inject.Inject;
import com.google.inject.Singleton;

import com.idealighter.game.server.ExecutorMgr;
import com.idealighter.game.server.core.task.ReqHttpMsgTask;
import com.idealighter.game.server.net.http.ReqHttpMessage.ResponseBo;
import com.idealighter.game.server.net.http.ReqHttpMessage.SessionBo;
import com.idealighter.utils.check.EmptyUtil;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
@Sharable
public class WebHttpServerHandler extends SimpleChannelInboundHandler<Object> {
  // 日志
  private static final Logger LOG = LoggerFactory.getLogger(WebHttpServerHandler.class);
  public static final String sessionAttr = "sessionId";
  private static final Map<String, SessionBo> sessionMap =
      new ConcurrentHashMap<String, SessionBo>();
  private final ExecutorMgr executorMgr;

  // 是否停服，停服后不再接受消息处理
  private boolean shutdown = false;

  @Inject
  public WebHttpServerHandler(ExecutorMgr executorMgr) {
    this.executorMgr = executorMgr;
  }

  @Override
  protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
    // super.channelRead(ctx, msgWapper);
    if (shutdown) {
      return;
    }

    if (msg instanceof FullHttpRequest) {
      FullHttpRequest httpRequest = (FullHttpRequest) msg;


      if ("/favicon.ico".equals(getPath(httpRequest))) {
        return;
      }

      // 获取session
      String sessionId = httpRequest.headers().get(sessionAttr);
      SessionBo session = null;
      if (EmptyUtil.stringIsNotEmpty(sessionId)) {
        session = sessionMap.get(sessionId);
      } else {
        session = new SessionBo();
        sessionId = session.getSessionId();
      }

      LOG.info("接收http消息: {}", getPath(httpRequest));

      ResponseBo response = new ResponseBo();

      ReqHttpMsgTask task =
          new ReqHttpMsgTask(new ReqHttpMessage(ctx, httpRequest, response, session));
      // 执行任务
      executorMgr.getAuthExecutor(sessionId).execute(task);
    }
  }

  private String getPath(FullHttpRequest httpRequest) {
    String url = httpRequest.uri();
    return url.replace(httpRequest.headers().get(HttpHeaderNames.HOST), "");
  }

  public void shutdown() {
    shutdown = true;
  }

  @Override
  public void channelReadComplete(ChannelHandlerContext ctx) {
    ctx.flush();
  }

  @Override
  public void channelActive(ChannelHandlerContext ctx) throws Exception {
    super.channelActive(ctx);
  }

  @Override
  public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    super.channelInactive(ctx);
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    cause.printStackTrace();
    if (ctx.channel().isActive()) {
      sendError(ctx, HttpResponseStatus.INTERNAL_SERVER_ERROR);
    }
  }

  private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
    FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status,
        Unpooled.copiedBuffer("{}", CharsetUtil.UTF_8));
    response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=utf-8");

    // Close the connection as soon as the error message is sent.
    ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
  }
}
